﻿using System;
using System.Collections.Generic;
using System.Linq;
using cfg.card;
using cfg.character;
using kemocard.Scripts.Common;
using kemocard.Scripts.Module.Battle;
using kemocard.Scripts.Pawn;
using Attribute = cfg.pawn.Attribute;

namespace kemocard.Scripts.Enemy;

public partial class E1 : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new Dictionary<string, string>
        {
            {
                "all_attack", "全体攻击，2000+(0.5*物理攻击)点物理地属性伤害"
            },
            { "self_pdefense", "自身/3回合/物理防御+5000" },
            { "self_pattack", "自身/99回合/物理攻击+2000,可叠加" },
            { "single_attack", "随机单体攻击，6000+(物理攻击)点物理地属性伤害" }
        };
    }

    public override List<string> UpdateActionId()
    {
        List<string> actionIds = ["all_attack", "self_pdefense", "single_attack", "self_pattack"];
        var turn = Mod?.TurnCount ?? 0;
        var r = new Random();
        // 随机选两个，排除加攻
        if (turn > 4) return [actionIds[r.Next(2)], actionIds[r.Next(2)]];
        return turn switch
        {
            1 => ["self_pattack", "all_attack"],
            2 => ["self_pdefense", "single_attack"],
            3 => ["self_pattack", "single_attack"],
            4 => ["all_attack", "all_attack"],
            _ => []
        };
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "all_attack":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = action =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = action.Target;
                            damage.Value = (int)(2000 + action.User.PAttack * 0.5f);
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.PATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>()
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "self_pdefense":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Guard,
                        Action = _ =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("HAMSTER_SPD", parent);
                            if (buff != null)
                            {
                                parent.AddBuff(buff);
                            }
                        },
                        User = parent,
                        Target = [parent]
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
                case "self_pattack":
                    var action3 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = _ =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("HAMSTER_SPA", parent);
                            if (buff != null)
                            {
                                parent.AddBuff(buff);
                            }
                        },
                        User = parent,
                        Target = [parent]
                    };
                    queue.Enqueue(action3, action3.Priority);
                    break;
                case "single_attack":
                    var action4 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = action4 =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = action4.Target;
                            damage.Value = 6000 + action4.User.PAttack;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.PATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1),
                    };
                    queue.Enqueue(action4, action4.Priority);
                    break;
            }
        }
    }
}

public partial class BatEarth : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new Dictionary<string, string>()
        {
            { "add_max_health", "自身/99回合/提高50000点最大生命值" },
            { "all_attack", "全体攻击，造成7500点物理地属性伤害，回复造成伤害的50倍的生命" },
            { "self_pattack", "自身/99回合/物理攻击+2000" },
            { "single_attack", "单体攻击，造成7500点物理地属性伤害，回复固定50000点生命" }
        };
    }

    public override List<string> UpdateActionId()
    {
        var actionIds = new List<string>
        {
            "add_max_health",
            "all_attack",
            "single_attack"
        };
        var r = new Random();
        List<string> result = [actionIds[r.Next(2)]];
        var turn = Mod?.TurnCount ?? 0;
        if ((turn & 1) == 0)
        {
            result.Add("self_pattack");
        }

        return result;
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "add_max_health":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Support,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("ADD_MAX_HEALTH_10000", enemyAction.User);
                            if (buff == null) return;
                            buff.IsUnique = false;
                            buff.StackLimit = 99;
                            enemyAction.User.AddBuff(buff);
                        },
                        User = parent
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "all_attack":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 7500 + enemyAction.User.PAttack;
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.PATTACK];
                            damage.OnHit += OnHit;
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>(),
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
                case "single_attack":
                    var action3 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 7500 + enemyAction.User.PAttack;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.PATTACK];
                            damage.OnHit += OnDamageOnHit;
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1),
                    };
                    queue.Enqueue(action3, action3.Priority);
                    break;
                case "add_pattack":
                    var action4 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Support,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("ADD_PATTACK_2000", enemyAction.User);
                            if (buff == null) return;
                            buff.IsUnique = false;
                            buff.StackLimit = 99;
                            enemyAction.User.AddBuff(buff);
                        },
                        User = parent
                    };
                    queue.Enqueue(action4, action4.Priority);
                    break;
            }
        }
    }

    private void OnDamageOnHit(Damage d, BasePawn p, float v)
    {
        var heal2 = new HealStruct()
        {
            Value = 50000,
            Role = d.User.Role,
            Attribute = d.Attribute,
            Target = [d.User],
            User = d.User,
        };
        Mod?.DoHeal(heal2);
    }

    private void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var heal = new HealStruct()
        {
            Value = (int)(arg3 * 0.5f),
            Role = arg1.User.Role,
            Attribute = arg1.Attribute,
            Target = [arg1.User],
            User = arg1.User,
        };
        Mod?.DoHeal(heal);
        arg1.OnHit -= OnHit;
    }
}

public partial class WormEarth : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new Dictionary<string, string>
        {
            { "all_mddown", "全体/3回合/魔法防御-3000" },
            { "single_taunt", "单体/3回合/嘲讽:1" },
            { "single_attack", "单体攻击，造成7500点魔法地属性伤害2次" },
            { "all_attack", "全体攻击，造成4000点魔法地属性伤害" }
        };
    }

    public override List<string> UpdateActionId()
    {
        var actionIds = new List<string>
        {
            "all_mddown",
            "single_taunt",
            "single_attack",
            "all_attack"
        };
        var r = new Random();
        List<string> result = [actionIds[r.Next(0, 1)], actionIds[r.Next(2, 3)]];
        return result;
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "all_mddown":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Block,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("ACID_WORM_MDDOWN", enemyAction.User);
                            if (buff == null) return;
                            enemyAction.Target.ForEach(p => p.AddBuff(buff));
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>()
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "single_taunt":
                    if (Mod?.Teammates == null) return;
                    var action1 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Support,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("TAUNT1", enemyAction.User);
                            if (buff == null) return;
                            enemyAction.Target.ForEach(p => p.AddBuff(buff));
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action1, action1.Priority);
                    break;
                case "single_attack":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 7500 + enemyAction.User.MAttack;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.MATTACK];
                            damage.Times = 2;
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
                case "all_attack":
                    var action3 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 4000 + enemyAction.User.MAttack;
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.MATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>()
                    };
                    queue.Enqueue(action3, action3.Priority);
                    break;
            }
        }
    }
}

public partial class SlimeEarth : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new Dictionary<string, string>
        {
            { "recover", "回复50000点生命" },
            { "all_mddown", "全体/2回合/魔法防御-5000" },
            { "single_attack", "单体攻击，造成10000点魔法地属性伤害" },
            { "all_attack", "全体攻击，造成4000点魔法地属性伤害" }
        };
    }

    public override List<string> UpdateActionId()
    {
        List<string> res = [];
        var actionIds = new List<string>
        {
            "all_mddown",
            "single_attack",
            "all_attack"
        };
        Random r = new();
        res.Add(actionIds[r.Next(3)]);
        res.Add("recover");
        return res;
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "recover":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Heal,
                        Action = enemyAction =>
                        {
                            var heal = new HealStruct()
                            {
                                User = enemyAction.User,
                                Target = [enemyAction.User],
                                Value = 50000,
                                Attribute = (int)Attribute.EARTH,
                                Role = Role.SUPPORT
                            };
                            Mod?.DoHeal(heal);
                        },
                        User = parent,
                        Target = [parent]
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "all_mddown":
                    var action1 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Block,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("SLIME_MDDOWN", enemyAction.User);
                            if (buff == null) return;
                            enemyAction.Target.ForEach(p => p.AddBuff(buff));
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>()
                    };
                    queue.Enqueue(action1, action1.Priority);
                    break;
                case "single_attack":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 10000 + enemyAction.User.MAttack;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.MATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
                case "all_attack":
                    var action3 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(enemyAction.User);
                            damage.Target = enemyAction.Target;
                            damage.Value = 4000 + enemyAction.User.MAttack;
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.MATTACK];
                            Mod?.DoDamage(damage);
                        }
                    };
                    queue.Enqueue(action3, action3.Priority);
                    break;
            }
        }
    }
}

public partial class Swan : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new()
        {
            { "special_attack", "单体攻击，造成500点地属性物理伤害，目标水属性的场合、改为10000点" },
            { "all_attack", "全体攻击，造成5000点地属性物理伤害" },
            { "single_attack", "单体攻击，造成7500点地属性物理伤害，无视防御" }
        };
    }

    public override List<string> UpdateActionId()
    {
        // if (Mod?.TurnCount == 0) return ["counter_attack"];
        List<string> res = ["special_attack"];
        var actionIds = new List<string>
        {
            "all_attack",
            "single_attack"
        };
        Random r = new();
        res.Add(actionIds[r.Next(2)]);
        return res;
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "counter_attack":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Support,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("SWAN_COUNTER", enemyAction.User);
                            if (buff != null) enemyAction.User.AddBuff(buff);
                        },
                        User = parent,
                        Target = [parent]
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "all_attack":
                    var action1 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 5000;
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.PATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action1, action1.Priority);
                    break;
                case "single_attack":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 7500;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.PATTACK];
                            damage.Modifiers.TryAdd(DamageModifier.NoGuard, 1);
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
            }
        }
    }
}

public partial class LizEarth : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new()
        {
            { "counter_attack_buff", "上反击buff" },
            { "counter_attack", "本回合受到魔法伤害的场合，全体攻击，造成5000*受到的魔法伤害的攻击的次数的地属性物理伤害" },
            { "all_attack", "全体攻击，造成5000点地属性物理伤害" },
            { "single_attack", "单体攻击，造成7500点地属性物理伤害" }
        };
    }

    public override List<string> UpdateActionId()
    {
        if (Mod?.TurnCount == 0) return ["counter_attack_buff"];
        List<string> res = ["counter_attack"];
        var actionIds = new List<string>
        {
            "all_attack",
            "single_attack",
        };
        Random r = new();
        res.Add(actionIds[r.Next(2)]);
        return res;
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
        foreach (var id in actionId)
        {
            switch (id)
            {
                case "counter_attack_buff":
                    var action = new EnemyAction()
                    {
                        Priority = PriorityDefines.Support,
                        Action = enemyAction =>
                        {
                            var buff = StaticUtil.NewBuffOrNullById("LIZ_EARTH_COUNTER", enemyAction.User);
                            if (buff != null) enemyAction.User.AddBuff(buff);
                        },
                        User = parent,
                        Target = [parent]
                    };
                    queue.Enqueue(action, action.Priority);
                    break;
                case "counter_attack":
                    break;
                case "all_attack":
                    var action1 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 5000;
                            damage.Tags = [Tag.AE, Tag.EARTH, Tag.PATTACK];
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = Mod?.Teammates.ToList<BasePawn>(),
                    };
                    queue.Enqueue(action1, action1.Priority);
                    break;
                case "single_attack":
                    var action2 = new EnemyAction()
                    {
                        Priority = PriorityDefines.Attack,
                        Action = enemyAction =>
                        {
                            var damage = CreateDamageFromOwner(parent);
                            damage.Target = enemyAction.Target;
                            damage.Value = 7500;
                            damage.Tags = [Tag.SE, Tag.EARTH, Tag.PATTACK];
                            damage.Modifiers.TryAdd(DamageModifier.NoGuard, 1);
                            Mod?.DoDamage(damage);
                        },
                        User = parent,
                        Target = GetRandomTarget(1)
                    };
                    queue.Enqueue(action2, action2.Priority);
                    break;
            }
        }
    }
}

public partial class TutorialPawn : EnemyScript
{
    public override Dictionary<string, string> GetActionDesc()
    {
        return new Dictionary<string, string>
        {
            { "none", "什么都不做" }
        };
    }

    public override List<string> UpdateActionId()
    {
        return ["none"];
    }

    public override void Action(BattleEnemy parent, List<string> actionId, PriorityQueue<EnemyAction, int> queue)
    {
    }
}